
/**
 * 使用规则
 * 自行配置remoteAssetsUrl资源地址
 * -v 输入要生成的版本号
 * -p 是否更新assets内的配置文件(默认更新)
 * 
 * 使用方法
 * node version_generator.js -v 1.0.0 -p false
 */

var fs = require('fs');
var path = require('path');
var crypto = require('crypto');
var exec = require('child_process').exec;

// 正式服
var remoteAssetsUrl = 'http://localhost/tutorial-hot-update/remote-assets/';

// 测试服
// var remoteAssetsUrl = 'http://localhost/tutorial-hot-update/remote-assets/';

var manifest = {
    packageUrl: remoteAssetsUrl,
    remoteManifestUrl: remoteAssetsUrl + 'project.manifest',
    remoteVersionUrl: remoteAssetsUrl + 'version.manifest',
    version: '1.0.0',
    assets: {},
    searchPaths: []
};

var dest = 'native/package/';
var src = 'native/package/';

// 是否更新assets内的配置文件
var isUpdatePackageConfig = true
var packagePath = 'assets/'

// Parse arguments
var i = 2;
while (i < process.argv.length) {
    var arg = process.argv[i];
    switch (arg) {
        case '-v':
            manifest.version = process.argv[i + 1];
            i += 2;
            break;
        case '-p':
            isUpdatePackageConfig = Boolean(process.argv[i + 1]);
            i += 2;
            break;
        default:
            i++;
            break;
    }
}

/**
 * 
 * @param {*} input build/jsb-link/res/
 * @param {*} output native/package/res
 */
function copyRes(input, output) {
    return new Promise((resolve, reject) => {
        exec(`cp -r ${input} ${output}`, function (err) {
            if (err) {
                console.log('err', err);
            } else {
                resolve();
            }
        });
    });
}

function readDir(dir, obj) {
    var stat = fs.statSync(dir);
    if (!stat.isDirectory()) {
        return;
    }
    var subpaths = fs.readdirSync(dir), subpath, size, md5, compressed, relative;
    for (var i = 0; i < subpaths.length; ++i) {
        if (subpaths[i][0] === '.') {
            continue;
        }
        subpath = path.join(dir, subpaths[i]);
        stat = fs.statSync(subpath);
        if (stat.isDirectory()) {
            readDir(subpath, obj);
        }
        else if (stat.isFile()) {
            // Size in Bytes
            size = stat['size'];
            md5 = crypto.createHash('md5').update(fs.readFileSync(subpath)).digest('hex');
            compressed = path.extname(subpath).toLowerCase() === '.zip';

            relative = path.relative(src, subpath);
            relative = relative.replace(/\\/g, '/');
            relative = encodeURI(relative);
            obj[relative] = {
                'size': size,
                'md5': md5
            };
            if (compressed) {
                obj[relative].compressed = true;
            }
        }
    }
}

var mkdirSync = function (path) {
    try {
        fs.mkdirSync(path);
    } catch (e) {
        if (e.code != 'EEXIST') throw e;
    }
}

function writeFile(file) {
    return new Promise((resolve, reject) => {
        fs.writeFile(file, JSON.stringify(manifest), (err) => {
            if (err) throw err;
            resolve();
        });
    });
}

function zipRes() {
    return new Promise((resolve) => {
        exec(`zip -q -r ${src}res ${src}src/ ${src}project.manifest ${src}version.manifest`, function (err) {
            if (err) throw err;
            resolve();
        });
    });
}

function delay(time) {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve();
        }, time * 1000);
    })
}

async function run() {
    // copy res and src
    await copyRes("build/jsb-link/res/", "native/package/res/")
    await copyRes("build/jsb-link/src/", "native/package/src/")
    console.log("[生产热更新资源]", "res和src资源拷贝完毕");

    // Iterate res and src folder
    readDir(path.join(src, 'src'), manifest.assets);
    readDir(path.join(src, 'res'), manifest.assets);

    var destManifest = path.join(dest, 'project.manifest');
    var destVersion = path.join(dest, 'version.manifest');

    // create dir
    mkdirSync(dest);
    console.log("[生产热更新资源]", "dest目录生成完毕");

    // write project.mainfest
    await writeFile(destManifest);

    if (isUpdatePackageConfig)
        await writeFile(path.join(packagePath, 'project.manifest'));

    console.log("[生产热更新资源]", "project.mainfest完毕");

    delete manifest.assets;
    delete manifest.searchPaths;

    // write version.mainfest
    await writeFile(destVersion)

    if (isUpdatePackageConfig)
        await writeFile(path.join(packagePath, '.manifest'));

    console.log("[生产热更新资源]", "version.mainfest完毕");

    await zipRes();
    console.log("[生产热更新资源]", "资源压缩完毕");

    console.log("[生产热更新资源]", "自动上传至CDN完毕");
}

run()
